#include <stdlib.h>
#include <string.h>

#include "map.h"

static void
map_dispose_free(Disposer *disposer, uint32_t key_len, void *dat)
{
	void *val = map_val(dat, key_len);

	if (disposer)
		disposer->dispose(val, disposer->extra);

	free(dat);
}

void
map_dispose(Map *map)
{
	set_dispose(map, map_dispose_free);
}

Nit_error
map_add(Map *map, uint32_t key_len, const void *key, void *val)
{
	void *dat = malloc(key_len + sizeof(val));
        Nit_error error;

	if (!dat)
		return NIT_ERROR_MEMORY;

	memcpy(dat, key, key_len);
	memcpy(((char *) dat) + key_len, &val, sizeof(val));

	if ((error = set_add(map, key_len, dat))) {
		free(dat);
		return error;
	}

	return error;
}

Nit_error
map_remove(Map *map, uint32_t key_len, const void *key, void **val)
{
        Nit_error error;
	void *tmp;

	*val = (void *) key;

	if ((error = set_remove(map, key_len, val)))
		return error;

	tmp = *val;
	*val = map_val(tmp, key_len);
	free(tmp);
	return error;
}

int
map_get(const Map *map, uint32_t key_len, const void *key, void **val)
{
	void *tmp;

	*val = (void *) key;

	if (!set_get(map, key_len, val))
		return 0;

	tmp = *val;
	*val = map_val(tmp, key_len);
	return 1;
}


void *
map_val(void *dat, uint32_t key_len)
{
	return *(void **) ((char *) dat + key_len);
}
